/**
 * 
 */
package idv.takeshi.software.productline.bookstore.application.service.spring;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.mail.MessagingException;

import org.apache.commons.lang.Validate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import idv.takeshi.software.productline.bookstore.application.service.MailService;
import idv.takeshi.software.productline.bookstore.application.service.PayCreditCardService;
import idv.takeshi.software.productline.bookstore.application.service.dto.CreditCardDto;
import idv.takeshi.software.productline.bookstore.domain.model.order.CreditCard;
import idv.takeshi.software.productline.bookstore.domain.model.order.Invoice;
import idv.takeshi.software.productline.bookstore.domain.model.order.Order;
import idv.takeshi.software.productline.bookstore.domain.model.order.OrderRepository;
import idv.takeshi.software.productline.bookstore.domain.model.useraccount.Clerk;
import idv.takeshi.software.productline.bookstore.domain.model.useraccount.UserAccount;
import idv.takeshi.software.productline.bookstore.domain.model.useraccount.UserAccountRepository;
import idv.takeshi.software.productline.bookstore.utils.invoice.InvoiceNumberUtils;
import idv.takeshi.software.productline.bookstore.utils.template.TemplateUtils;

/**
 * A service implementation for paying by creditCard operation.
 * @author takeshi
 *
 */
@Service("payCreditCardService")
@Transactional
public class PayCreditCardServiceImpl implements PayCreditCardService {
	
	private static final Log log = LogFactory.getLog(PayCreditCardServiceImpl.class);
	
	@Autowired
	private UserAccountRepository userAccountRepository;
	
	@Autowired
	private OrderRepository orderRepository;
	
	@Autowired
	private MailService mailService;
	
	@Autowired
	private MessageSource messageSource;
	
	private String templatePath;
	
	/* (non-Javadoc)
	 * @see idv.takeshi.software.productline.bookstore.application.service.PayCreditCardService#getOrderById(java.lang.Long)
	 */
	public Order getOrderById(Long id) {
		return this.orderRepository.findById(id);
	}

	
	/* (non-Javadoc)
	 * @see idv.takeshi.software.productline.bookstore.application.service.PayCreditCardService#updateCreditCard(idv.takeshi.software.productline.bookstore.application.service.dto.CreditCardDto, java.lang.Long, java.util.Locale)
	 */
	public void updateCreditCard(CreditCardDto creditCardDto, Long orderId, Locale locale) {
		Validate.notNull(creditCardDto, "creditCardDto shall always not be null");
		Validate.notNull(orderId, "orderId shall alwasy not be null");
		CreditCard creditCard = null;
		Invoice invoice = null;
		Date dateTime = null;
		Order order = null;
		
		order = this.orderRepository.findById(orderId);
		invoice = order.getInvoice();
		invoice.setInvoiceNumber(InvoiceNumberUtils.generateRandomInvoiceNumber());
		creditCard = (CreditCard) order.getPayment();
		creditCardDto.loadModel(creditCard);
		creditCard.setPaid(true);
		
		dateTime = new Date();
		invoice.setUpdateTime(dateTime);
		creditCard.setUpdateTime(dateTime);
		order.setUpdateTime(dateTime);
		
		UserAccount userAccount = this.userAccountRepository.findByOrderId(order.getId());
		Validate.notNull(userAccount, "userAccount shall always not be null");
		//send notice mail
		sendNoticeMail(userAccount, order, locale);
	}
	
	/**
	 * @return the templatePath
	 */
	public String getTemplatePath() {
		return templatePath;
	}


	/**
	 * @param templatePath the templatePath to set
	 */
	public void setTemplatePath(String templatePath) {
		this.templatePath = templatePath;
	}


	private void sendNoticeMail(UserAccount userAccount, Order order, Locale locale){
		String subject = null;
		String content = null;
		Map<String, Object> root = new HashMap<String, Object>();
		
		subject = this.messageSource.getMessage(
				"mail.order.creditCard.subject", new String[]{"" + order.getId()}, locale);
		
		root.put("userName", userAccount.getUserName());
		root.put("order", order);
		
		content = TemplateUtils.generateTemplateString(this.templatePath, "payOrderByCreditCard.ftl", root, locale);
		
		try {
			List<String> clerkMailAddresses = this.userAccountRepository.findEmailAddressesByRole(Clerk.class);
			if(clerkMailAddresses.size() > 0){
				
					this.mailService.send(clerkMailAddresses.toArray(new String[]{}), subject, content, true);
				
			}
			this.mailService.send(userAccount.getEmailAddress(), subject, content, true);
		} catch (MessagingException e) {
			log.error("send pay by credit card notice mail failed", e);
		}
	}

}
